# -*- coding: utf-8 -*-
import time
from universal.common_header import *
from universal.common_header_widget import *
from Module.TrainAndTest.TrainAndTest_Paint import PaintArea
from mylibs.XmlWriter import SaveProjectToXml

from PyQt5.QtCore import QRectF
from DeepLearning.project.util_my import main, get_configs,get_projects
from universal.widget_common import Table_widget,Table_widget_setItem,\
    lineEdit_act_file,lineEdit_act,createLabel,SetCellWidget,SetReadOnly
from Module.xRayDetection.extra_page import QComboCheckBox,QComboCheckBox_all
from Module.xRayDetection.xray.xray import tolabmelme
from DeepLearning.project.util_my import get_formats
from mylibs.color import get_rotation
from multiprocessing import Process, Queue

class TestWidget(QWidget):
    my_signal = pyqtSignal(object,str)
    show_signal = pyqtSignal(object,str)
    def __init__(self, parent=None):
        super(TestWidget, self).__init__(parent)
        # self.setStyleSheet("font:10pt %s;border-width: 1px;border-style: solid;border-color: rgb(41, 112, 69);"%FONTSTR)
        # self.setPalette(QPalette(QColor(61,161,191)))
        # self.setAutoFillBackground(True)
        self.leftwidget = QWidget()
        self.testRightContainer = QWidget()
        self.TestMainLayout = QHBoxLayout(self)
        self.TestLeftLayout = QVBoxLayout(self.leftwidget)
        self.TestRightLayout = QVBoxLayout(self.testRightContainer)
        TabelParameter_Show = self.Show_Result()  # self.TabelParameter_Show
        self.Tab()
        self.label = PaintArea()
        self.TestPicturesWidget = showTestPic()
        self.TestPicturesWidget.TextBrowser = self.TextBrowser
        self.TestLeftLayout.addWidget(self.TabWidget)
        self.TestLeftLayout.addWidget(TabelParameter_Show)
        self.TestRightLayout.addWidget(self.label)
        self.TestRightLayout.addWidget(self.TestPicturesWidget)
        # self.TestMainLayout.addWidget(self.testLeftContainer)
        self.TestMainLayout.addWidget(self.testRightContainer)
        self.init_parameter()
        self.my_signal.connect(TextBrowserNews)
        self.show_signal.connect(self.ShowResultImg)

    def Tab(self):
        self.TabWidget = QTabWidget()
        TabelParameter_Input = self.Input_Value()
        self.TextBrowser_()
        self.TabWidget.addTab(TabelParameter_Input, "预测参数")
        self.TabWidget.addTab(self.TextBrowser, "运行信息")

    def TextBrowser_(self):
        self.TextBrowser = QTextBrowser()
        self.TextBrowser.document().setMaximumBlockCount(100)
        self.TextBrowser.append('------信息框------')

    def init_parameter(self):
        self.od_cfg = {}
        self.DetectModelPath = ''
        self.TestImagesPath = ''
        self.SaveOKImages = ''
        self.SaveNGImages = ''
        self.Score = '0.45'
        self.proj_dir = ''
        self.device_list = []
        self.IOU = '0.55'
        self.TotalTestImages = ''
        self.labelClasses = ''
        self.NGImagesNum = ''
        self.NGImagesRate = ''
        self.TestTime = ''
        self.TestDate = ''
        self.ini_ = 1
        self.alreadyNGImg = 0
        self.alreadyNGRate = 0
        self.projectTask = ''
        # self.main = queue.Queue()
        self.main = Queue()
        self.resultParaPath = ''
        self.englishTask = ''
        self.OKLIST = []
        self.NGLIST = []
        self.Combox = True
        self.Line = True
        self.refreshTestInerface()   #setText参数

    def Input_Value(self):
        TabelParameter_Input = Table_widget(self, 9, 2)
        name_list = ['图像路径', "自定义模型路径", "自定义模型框架",
                     "预置推理模型", '结果储存路径', "Device", "confidence:", "开始&关闭", "模型导出格式"]
        Table_widget_setItem(TabelParameter_Input, name_list)

        self.testimgspathLineEdit = lineEdit_act(self)
        self.weightpathLineEdit = lineEdit_act_file(self, "Pt files (*.pt)")
        self.weightpathLineEdit.textChanged.connect(lambda: self.LineEvent())
        self.weightpathLineEdit.setPlaceholderText("若没有自定义模型,请选择预置模型测试")
        self.weightModel_Frame = QComboBox(self)
        ModelFrame = get_projects()
        if '__pycache__' in ModelFrame:
            ModelFrame.remove('__pycache__')
        self.weightModel_Frame.addItem('OD')
        # self.weightModel_Frame.addItems(ModelFrame)
        self.modelComBox = QComboBox(self)  # 1
        self.modelComBox.currentTextChanged.connect(lambda: self.ComboxEvent())
        self.resultParaLineEdit = lineEdit_act(self)
        self.selectDevice = QComboCheckBox()
        self.scoreLineEdit = QLineEdit('')
        self.startTestBtn = QPushButton('Start Detecting')
        self.startTestBtn.setStyleSheet("background-color:rgb(0,125,0)")
        self.startTestBtn.clicked.connect(self.startTest)

        self.ModelFormat = QComboCheckBox_all(get_formats())
        self.ModelFormat.select_all()
        TabelParameter_Show_list = [self.testimgspathLineEdit, self.weightpathLineEdit, self.weightModel_Frame,self.modelComBox,
                                    self.resultParaLineEdit, self.selectDevice, self.scoreLineEdit, self.startTestBtn,self.ModelFormat]
        SetCellWidget(TabelParameter_Input, TabelParameter_Show_list)

        self.ExportModel = QPushButton('导出模型')
        self.ExportModel.setStyleSheet('''QPushButton{background:rgb(0,125,0);
            border-radius:5px;}QPushButton:hover{background:blue;}''')
        self.ExportModel.clicked.connect(self.ExportModel_)
        TabelParameter_Input.insertRow(9)
        TabelParameter_Input.setSpan(9,0,1,2)  #合并的行数；列数；需要合并几行；几列
        TabelParameter_Input.setCellWidget(9, 0, self.ExportModel)

        return TabelParameter_Input

    def Show_Result(self):
        TabelParameter_Show = Table_widget(self, 5, 2)

        name_list = ["总图像数",'已推理的图像数', "NG图像数量", "NG图像比率", "总推理时间/s"]
        Table_widget_setItem(TabelParameter_Show, name_list)
        self.totaltestimgshowlabel = QLineEdit('')
        self.AlreadyTestImg = QLineEdit('')
        self.NGimgshowlabel = QLineEdit('')
        self.NGimgsRateshowlabel = QLineEdit('')
        self.totaltesTimeshowlabel = QLineEdit('')
        TabelParameter_Show_list = [self.totaltestimgshowlabel, self.AlreadyTestImg, self.NGimgshowlabel,
            self.NGimgsRateshowlabel, self.totaltesTimeshowlabel]
        SetReadOnly(TabelParameter_Show_list)
        SetCellWidget(TabelParameter_Show, TabelParameter_Show_list)

        return TabelParameter_Show

    def LineEvent(self):
        if self.Line == True:
            self.Combox = False
            self.modelComBox.setCurrentIndex(-1)
            self.Combox = True

    def ComboxEvent(self):
        if self.Combox == True:
            self.Line = False
            self.weightpathLineEdit.setText('')
            self.Line = True

    def ExportModel_(self):
        self.Model_Format = self.ModelFormat.currentText().split(";")

        self.SetValue()
        sub = queue.Queue()

        kwargs = {
            'action': 'export',  # train infer export results configs refactor
            'task': self.englishTask,  # classification detection segmentation
            'cfg_id': self.modelComBox_text or self.weightFrame,  # config id    #框架/初始权重###
            'device': self.device,
            'sub_queue':sub, # cpu or 0 or 0,1...
            'out_dir': os.path.dirname(self.DetectModelPath),  # save action results
            'weights': self.DetectModelPath,  # weights path
            'frameworks': self.Model_Format,
            'github_dir': os.path.join(dir_root(), 'DeepLearning', 'downloads'),
        }
        self.FormatThread = threading.Thread(target=main, kwargs=kwargs)
        self.FormatThread.daemon = True
        self.FormatThread.start()
        self.TextBrowser.append('导出开始')
        self.GetFormatThread = threading.Thread(target=self.GetVal, args=(None,sub,True))
        self.GetFormatThread.daemon = True
        self.GetFormatThread.start()

    def SaveSetting(self):
        try:
            self.TestDate = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
            self.od_cfg["testImgsPath"] = self.TestImagesPath
            self.od_cfg["testModelPath"] = self.DetectModelPath
            self.od_cfg["SaveOKimgsPath"] = self.SaveOKImages
            self.od_cfg["SaveNGimgsPath"] = self.SaveNGImages
            self.od_cfg["testScore"] = self.Score
            self.od_cfg["totaltestimgs"] = self.AllImg
            self.od_cfg["ngImgsNum"] = str(self.alreadyNGImg)
            self.od_cfg["ngImgsRate"] = self.alreadyNGRate
            self.od_cfg["totaltesttime"] = self.TestTime
            self.od_cfg["testDate"] = self.TestDate
            SaveProjectToXml(self.od_cfg,None)
        except Exception as e:
            self.TextBrowser.append('Function:SaveSetting')
            self.TextBrowser.append(str(e))

    def AddModelSelect(self):
        try:
            if self.projectTask == '目标检测':
                self.englishTask = 'detection'
                self.model_False = ["OD_n","OD_n2","OD_s","OD_s2","OD_m","OD_m2","OD_l","OD_l2","OD_x","OD_x2"]
            if self.projectTask == '图像分类':
                self.englishTask = 'classification'
                self.model_False = ["OD_n_cls", "OD_s_cls", "OD_m_cls", "OD_l_cls", "OD_x_cls", "OD_e_cls_0", "OD_e_cls_1",
                                    "OD_e_cls_2", "OD_e_cls_3", "OD_r_cls_0", "OD_r_cls_1", "OD_r_cls_2", "OD_r_cls_3"]
            if self.projectTask == '语义分割':
                self.englishTask = 'detection'
            if self.projectTask == '实例分割':
                self.englishTask = 'segmentation'
                self.model_False = ["OD_n_seg","OD_s_seg","OD_m_seg","OD_l_seg","OD_x_seg"]

            self.model_true = get_configs(self.englishTask)
            for i in self.model_False:
                self.modelComBox.addItem(str(i))
        except Exception as e:
            self.TextBrowser.append('Function:AddModelSelect')
            self.TextBrowser.append(str(e))

    def ButtonColor(self):
        self.startTestBtn.setText('开始')
        self.startTestBtn.setStyleSheet('''QPushButton{background:rgb(0,125,0);
            border-radius:5px;}QPushButton:hover{background:blue;}''')

    def startTest(self):
        try:
            self.AllImg = 0
            if self.ini_ == 0:
                self.main.put({'stop': True})
                self.ButtonColor()
                self.EndTestTime = time.time()
                self.TestPicturesWidget.rundetect = False
                self.TestTime = round(self.EndTestTime - self.StartTestTime,4)
                self.SaveSetting()
                self.AddItem()
                self.ini_ = 1
                return
            else:
                # self.main.queue.clear()
                self.startTestBtn.setText('停止')
                self.startTestBtn.setStyleSheet('''QPushButton{background:rgb(255,0,0);
                           border-radius:5px;}QPushButton:hover{background:blue;}''')
                self.ini_ = 0
                self.AreadyImg = 0
                self.TestPicturesWidget.Piclist.clear()
                self.TestPicturesWidget.Page.clear()
                self.TestPicturesWidget.rundetect = True
                self.class_all_path = []
                self.class_all_name = ['ALL']
                kwargs, sub= self.Load_Parameter()

                self.StartTestTime = time.time()
                self.TestThread = Process(target=main, kwargs=kwargs)
                self.TestThread.daemon = True
                self.TestThread.start()

                self.GetValThread = threading.Thread(target=self.GetVal, args=(self.main, sub))
                self.GetValThread.daemon = True
                self.GetValThread.start()
        except Exception as e:
            self.TextBrowser.append('Function:startTest')
            self.TextBrowser.append(str(e))

    def Load_Parameter(self):
        try:
            self.AlreadyTestImg.clear()
            self.NGimgshowlabel.clear()
            self.NGimgsRateshowlabel.clear()
            self.totaltesTimeshowlabel.clear()

            self.SetValue()

            shutil.rmtree(self.resultParaPath)
            MK_dir(self.resultParaPath)

            self.SaveOKImages = os.path.join(self.resultParaPath, 'OK')
            self.SaveNGImages = os.path.join(self.resultParaPath, 'NG')
            self.SaveNG_ImgResult = os.path.join(self.SaveNGImages, 'imgsResult')

            MK_dir(self.SaveNG_ImgResult)
            MK_dir(self.SaveOKImages)
            MK_dir(self.SaveNGImages)

            self.AllImg = len(get_img_list(self.TestImagesPath, [], ext=['jpg', 'png', 'JPG', 'jpeg'
                                                        , 'bmp', 'PNG', 'JPEG', 'BMP']))
            self.label.label1.setText('%s Images' % self.AllImg)
            self.totaltestimgshowlabel.setText(str(self.AllImg))
            self.alreadyNGImg = 0
            self.alreadyNGRate = 0
            self.Score = self.scoreLineEdit.text()
            self.IOU = 0.55

            self.result = [] #Another
            self.first = 1

            # sub = queue.Queue()
            sub = Queue()

            cfg = {
                'action': 'infer',  # train infer export results configs refactor
                'task': self.englishTask,  # classification detection segmentation
                'infer_dir': self.TestImagesPath,  # dataset directory  不能有images
                'cfg_id': self.modelComBox_text or self.weightFrame,  # config id    #初始权重
                'device': self.device,  # cpu or 0 or 0,1...
                'out_dir': self.resultParaPath,  # save action results
                'weights': self.DetectModelPath,  # weights path
                'conf_thres': self.Score,
                'github_dir': os.path.join(dir_root(), 'DeepLearning', '.github'),

                'sub_queue': sub,  # queue for sending data from sub thread to main thread, like "progress"
                'main_queue': self.main,  # queue for sending data from main thread to sub thread, like "stop"
                'logger': init_log(),  # custom logger object for logging
            }
            return cfg,sub

        except Exception as e:
            self.TextBrowser.append('Function:Load_Parameter')
            self.TextBrowser.append(str(e))

    def SetValue(self):
        try:
            self.TestImagesPath = self.testimgspathLineEdit.text()
            self.DetectModelPath = self.weightpathLineEdit.text()
            self.modelComBox_text = self.modelComBox.currentText()
            if self.projectTask == '图像分类':
                self.modelComBox_text = self.input_cls(self.modelComBox_text)
            else:
                model_index = self.model_False.index(
                    self.modelComBox_text) if self.modelComBox_text in self.model_False else -1
                if model_index < 0:
                    self.modelComBox_text = ""
                else:
                    self.modelComBox_text = self.model_true[model_index]
            # self.weightFrame = self.weightModel_Frame.currentText()
            self.weightFrame = "yolov5"
            self.resultParaPath = self.resultParaLineEdit.text()
            MK_dir(self.resultParaPath)
            if "c" in self.selectDevice.currentText() or 'C' in self.selectDevice.currentText():
                self.device = 'cpu'
            else:
                device_list = re.findall(r"\d+\.?\d*", self.selectDevice.currentText())
                self.device = str(",".join(device_list))
        except Exception as e:
            if e.args != ():
                self.TextBrowser.append('Function:SetValue')
                self.TextBrowser.append(str(e))

    def GetVal(self,main,sub,export=False):
        while True:
            time.sleep(0.1)
            if main!=None:
                try:
                    flags = main.get(block=False)
                except:
                    flags = {}
                if flags.get('stop', False):
                    main.put({'stop': True})
                    break
            try:
                if export:  #如果是导出模型

                    houzhui = os.path.splitext(self.DetectModelPath)[1]
                    if len(self.Model_Format)<2:
                        model1 = self.DetectModelPath.replace(houzhui, self.Model_Format[0])
                        if os.path.exists(model1):
                            self.TextBrowser.append('导出完成:'+self.Model_Format[0])
                            break
                    else:
                        model1 = self.DetectModelPath.replace(houzhui, '.'+self.Model_Format[0])
                        model2 = self.DetectModelPath.replace(houzhui, '.'+self.Model_Format[1])
                        if os.path.exists(model1) and os.path.exists(model2) :
                            self.TextBrowser.append(str('导出完成:'+str(self.Model_Format[0])+','+str(self.Model_Format[1])))
                            break

                else:   #如果是推理图片
                    result = sub.get(block=False)
                    if 'err' in result:
                        self.TextBrowser.append(result['err'])
                        self.ButtonColor()
                        self.TextBrowser.append('运行结束！')
                        self.ini_ = 1
                        break
                    elif self.projectTask == '图像分类':
                        if result['prob'] != []:
                            self.classVal(result)

                    elif self.projectTask == '实例分割':
                        self.SegVal(result)

                    elif self.projectTask == '目标检测':
                        self.detectVal(result)
                    self.AlreadyTestImg.setText(str(result['idx']))
                    self.AlreadyTime = time.time()
                    self.totaltesTimeshowlabel.setText(str(round(self.AlreadyTime - self.StartTestTime, 4)))
                    self.my_signal.emit(self.TextBrowser,result['path'])
                    if int(result['idx']) == int(self.AllImg):
                        time.sleep(0.5)
                        self.TestPicturesWidget.rundetect = False
                        self.ShowResultImg(result,self.SaveNG_ImgResult)
                        self.ButtonColor()
                        self.EndTestTime = time.time()
                        self.TestTime = round(self.EndTestTime - self.StartTestTime,4)
                        self.SaveSetting()
                        self.ini_ = 1
                        self.AddItem()
                        main.put({'stop': True})
                        break

            except Exception as e:
                if e.args != ():
                    self.TextBrowser.append('Function:GetVal')
                    self.TextBrowser.append(str(e))


    def SegVal(self,result):
        if len(result['segj']) != 0:
            point_size = 1
            point_color = (0, 0, 255)
            thickness = 2
            for idx, point in enumerate(result['segj']):  #画点
                point = (np.array(point) * [result['im'].shape[1], result['im'].shape[0]]).astype(int)

                result['im'] = self.fill(result['im'],point,alpha=0.5)
                for i in point:
                    cv2.circle(result['im'], i, point_size, point_color, thickness)

            for detail in result['det']:   #画框
                name = result['names'][detail[5]]
                detail[5] = name

            drawDetectBox_NoCls(result['im'],result['det'],self.SaveNG_ImgResult+os.sep+os.path.basename(result['path']))

        else:
            shutil.copy(result['path'], self.SaveOKImages)
        self.show_signal.emit(result, self.SaveNG_ImgResult)

    def classVal(self,result):

        index = result['prob'].index(max(result['prob']))
        name = result['names'][index]
        if name not in self.class_all_name:
            self.class_all_name.append(name)

        classPath = os.path.join(self.SaveNG_ImgResult, name)
        if not os.path.exists(classPath):
            os.makedirs(classPath)
        if classPath not in self.class_all_path:
            self.class_all_path.append(classPath)
        self.TestPicturesWidget.ClassPath = self.class_all_path

        STR = result['path'] + '    ' + name + '     ' + str(max(result['prob']))
        shutil.copy(result['path'], classPath)
        self.SAVE_TXT_add(classPath,STR)
        self.show_signal.emit(result, self.SaveNG_ImgResult)

    def detectVal(self,result):
        if result['det'] != []:
            if result['path'] != self.result:
                self.result = result['path']
                self.alreadyNGImg = self.alreadyNGImg + 1
                self.NGimgshowlabel.setText(str(self.alreadyNGImg))
                self.NG_IMG_LABEL = os.path.join(self.SaveNGImages, 'NG_Original')
                MK_dir(self.NG_IMG_LABEL)
                ImgSavePath = os.path.join(self.SaveNG_ImgResult, os.path.basename(result['path']))

                picture_thread = threading.Thread(target=self.picture, args=(result,ImgSavePath))
                picture_thread.daemon = True
                picture_thread.start()

                writexml_thread = threading.Thread(target=self.writexml, args=(result,))
                writexml_thread.daemon = True
                writexml_thread.start()
        else:
            shutil.copy(result['path'], self.SaveOKImages)

        show_signal_thread = threading.Thread(target=self.show_signal_image, args=(result,))
        show_signal_thread.daemon = True
        show_signal_thread.start()

    def picture(self,result,ImgSavePath):
        time3 = time.time()
        drawDetectBox_NoCls(result['im'], result['det'], ImgSavePath)
        shutil.copy(result['path'], self.NG_IMG_LABEL)
        time4 = time.time()
        print("time4-time3", time4 - time3)

    def writexml(self,result,obj1=None):
        time1 = time.time()
        jpgname = os.path.basename(result['path'])
        jpgnameNOext = os.path.splitext(jpgname)[0]
        xml = os.path.join(self.NG_IMG_LABEL + os.sep + jpgnameNOext + '.xml')
        xml_write = tolabmelme(result['path'], result['im'], result['det'],
                               names=list(result['names'].values()))
        time2 = time.time()
        print("time2-time1", time2 - time1)
        time11 = time.time()
        with open(xml, mode='w+', encoding='utf8') as xml_file:
            xml_file.write(xml_write)
        time22 = time.time()
        print("time22-time12", time22 - time11)

    def show_signal_image(self,result,obj1=None):
        self.show_signal.emit(result,self.SaveNG_ImgResult)

    def ShowResultImg(self, result, path):
        if self.projectTask == '图像分类':
            self.TestPicturesWidget.ClassSelect.clear()
            self.TestPicturesWidget.ClassName = self.class_all_name
            self.TestPicturesWidget.ClassChange_ = 'class'
            self.TestPicturesWidget.openIMG(scanAllImages(os.path.join(self.SaveNG_ImgResult)))
        else:
            self.TestPicturesWidget.NGImgList = self.NGLIST = scanAllImages(path)
            self.TestPicturesWidget.OKImgList = self.OKLIST = scanAllImages(self.SaveOKImages)
            if self.AreadyImg != int(result['idx']):
                self.TestPicturesWidget.openIMG(self.NGLIST + self.OKLIST)  # 显示图像
                self.AreadyImg = int(result['idx'])

            self.alreadyNGRate = int(self.alreadyNGImg) / int(result['idx'])
            self.alreadyNGRate = str(round(self.alreadyNGRate * 100, 4)) + "%"
            self.NGimgsRateshowlabel.setText(str(self.alreadyNGRate))

    def AddItem(self):
        self.TestPicturesWidget.ClassSelect.clear()
        if self.projectTask == '图像分类':
            self.TestPicturesWidget.ClassSelect.addItems(self.class_all_name)
        else:
            self.TestPicturesWidget.ClassSelect.addItems(['ALL', 'NG', "OK"])

    def fill(self,im, points, color=(100, 5, 55), alpha=1.0):
        import numpy
        mask = numpy.zeros(im.shape, dtype=np.uint8)
        cv2.fillPoly(mask, pts=[numpy.array(points).reshape(-1, 2)], color=color)
        im = cv2.addWeighted(im, 1, mask, alpha, 0)
        return im

    def SAVE_TXT_add(self, path,jizu):
        PosetiveEscapetxt = path + os.sep + "name" + '.txt'
        wr_txt = txtwr(PosetiveEscapetxt)
        wr_txt.write_add(jizu)

    def clearShow(self):
        self.modelComBox.clear()
        self.totaltestimgshowlabel.clear()
        self.AlreadyTestImg.clear()
        self.NGimgshowlabel.clear()
        self.NGimgsRateshowlabel.clear()
        self.totaltesTimeshowlabel.clear()
        self.label.label2.clear()

    def refreshTestInerface(self):
        try:
            self.weightpathLineEdit.setText(self.DetectModelPath)#
            self.testimgspathLineEdit.setText(self.TestImagesPath)
            self.scoreLineEdit.setText(self.Score)
            self.totaltestimgshowlabel.setText(self.TotalTestImages)
            self.NGimgshowlabel.setText(self.NGImagesNum)
            self.NGimgsRateshowlabel.setText(self.NGImagesRate)
            self.totaltesTimeshowlabel.setText(self.TestTime)
            self.resultParaLineEdit.setText(os.path.dirname(self.SaveNGImages))
            if self.TestDate != "":
                self.label.label2.setText('Date: ' + self.TestDate)

        except Exception as e:
            self.TextBrowser.append('Function:refreshTestInerface')
            self.TextBrowser.append(str(e))

    def getTestValue(self,para_Cfg):
        try:
            self.DetectModelPath = para_Cfg['testModelPath']
            self.TestImagesPath = para_Cfg['testImgsPath']
            self.SaveOKImages = para_Cfg['SaveOKimgsPath']
            self.SaveNGImages = para_Cfg['SaveNGimgsPath']
            self.Score = para_Cfg['testScore']
            self.IOU = para_Cfg['testIOU']
            self.TotalTestImages = para_Cfg['totaltestimgs']
            self.TestDate = para_Cfg['testDate']
            self.NGImagesNum = para_Cfg['ngImgsNum']
            self.NGImagesRate = para_Cfg['ngImgsRate']
            self.TestTime = para_Cfg['totaltesttime']
            self.refreshTestInerface()
        except Exception as e:
            self.TextBrowser.append('Function:getTestValue')
            self.TextBrowser.append(str(e))

    def input_cls(self, model):
        if model == "OD_n_cls":
            return "yolov5n-cls"

        elif model == "OD_s_cls":
            return "yolov5s-cls"

        elif model == "OD_m_cls":
            return "yolov5m-cls"

        elif model == "OD_l_cls":
            return "yolov5l-cls"

        elif model == "OD_x_cls":
            return "yolov5x-cls"

        elif model == "OD_e_cls_0":
            return "yolov5-efficientnet_b0"

        elif model == "OD_e_cls_1":
            return "yolov5-efficientnet_b1"

        elif model == "OD_e_cls_2":
            return "yolov5-efficientnet_b2"

        elif model == "OD_e_cls_3":
            return "yolov5-efficientnet_b3"

        elif model == "OD_r_cls_0":
            return "yolov5-resnet18"

        elif model == "OD_r_cls_1":
            return "yolov5-resnet34"

        elif model == "OD_r_cls_2":
            return "yolov5-resnet50"

        elif model == "OD_r_cls_3":
            return "yolov5-resnet101"
        else:
            return "yolov5n-cls"

# QListWidget用于显示图片
class showTestPic(QWidget):
    fanye = pyqtSignal()
    def __init__(self):
        super(showTestPic,self).__init__()
        self.setPalette(QPalette(QColor(61,161,191)))
        # self.setStyleSheet("background-color:rgb(30,40,75)")
        self.setAutoFillBackground(True)
        self.OKImgList = []
        self.NGImgList = []
        self.ClassName = []
        self.ClassPath = []
        self.rundetect = True
        self.ButtonOpen = False
        self.TextBrowser = None
        self.currentPage = 0
        self.imgInPage = 10  #一页显示多少张图像
        self.Piclist = QListWidget()
        self.Piclist.itemDoubleClicked.connect(self.sacleImage)
        self.Piclist.setResizeMode(QListView.Adjust)
        self.Piclist.setResizeMode(QListWidget.Adjust)
        self.Qlayout = QVBoxLayout(self)
        self.QButtonlayout = QHBoxLayout()

        self.FirstButton = QPushButton("首页")
        self.FirstButton.clicked.connect(self.FirstPage)
        self.LastButton = QPushButton("末页")
        self.LastButton.clicked.connect(self.LastPage)

        self.PreButton = QPushButton("上一页")
        self.PreButton.clicked.connect(self.PrePage)
        self.NextButton = QPushButton("下一页")
        self.NextButton.clicked.connect(self.NextPage)

        self.ButtonColor()

        self.Page = QComboBox()
        self.Page.currentIndexChanged.connect(self.comboxChange)
        self.fanye.connect(self.comboxChange_)

        self.ClassSelect = QComboBox()
        self.ClassSelect.currentIndexChanged.connect(self.ClassChange)
        self.ClassSelect.setMaximumWidth(80)
        self.ClassChange_ = 'detect'

        self.QButtonlayout.addWidget(self.FirstButton)
        self.QButtonlayout.addWidget(self.PreButton)
        self.QButtonlayout.addWidget(self.Page)
        self.QButtonlayout.addWidget(self.NextButton)
        self.QButtonlayout.addWidget(self.LastButton)
        self.QButtonlayout.addWidget(self.ClassSelect)
        self.Qlayout.addWidget(self.Piclist)
        self.Qlayout.addLayout(self.QButtonlayout)
        self.graphicsView = ImageView()
        self.graphicsView.buttonLeft.clicked.connect(self.PreImg)
        self.graphicsView.buttonRight.clicked.connect(self.NextImg)
        # self.QgraphicsView()

    def ButtonColor(self):
        self.FirstButton.setStyleSheet('''QPushButton{background:#91B822;
              border-radius:5px;}QPushButton:hover{background:#80D1C8;}''')
        self.LastButton.setStyleSheet('''QPushButton{background:#91B822;
              border-radius:5px;}QPushButton:hover{background:#80D1C8;}''')
        self.PreButton.setStyleSheet('''QPushButton{background:#8BA583;
                border-radius:5px;}QPushButton:hover{background:#CDA593;}''')
        self.NextButton.setStyleSheet('''QPushButton{background:#8BA583;
                border-radius:5px;}QPushButton:hover{background:#CDA593;}''')

    def QgraphicsView(self):
        try:
            self.graphicsView = QGraphicsView()
            self.graphicsView.setGeometry(QRect(300, 30, 300, 50))
            self.graphicsView.setFixedSize(200,100)
            self.graphicsView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            self.graphicsView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            buttonLeft = QPushButton('左')
            buttonLeft.clicked.connect(self.PreImg)
            buttonLeft.setMaximumSize(30, 30)
            buttonRight = QPushButton('右')
            buttonRight.clicked.connect(self.NextImg)
            buttonRight.setMaximumSize(30, 30)
            buttonLayout = QHBoxLayout()
            buttonLayout.addWidget(buttonLeft, Qt.AlignLeft)
            buttonLayout.addSpacing(5000)
            buttonLayout.addWidget(buttonRight, Qt.AlignRight)
            self.graphicsView.setLayout(buttonLayout)
            self.graphicsView.setObjectName("graphicsView")
            self.scene = QGraphicsScene()
        except Exception as e:
            self.TextBrowser.append('Function:QgraphicsView')
            self.TextBrowser.append(str(e))

    def openIMG(self,List,classchange=False):   #获取图像列表，页数等  显示图像在 comboxChange 的 ImgShowList
        try:
            self.imgList = List
            if len(self.imgList)>=0:
                time1 = time.time()
                self.ButtonOpen = True
                self.pageNum = math.ceil(int(len(self.imgList))/self.imgInPage)

                if classchange==True:
                    self.Page.clear()
                    for i in range(self.pageNum):
                        self.Page.addItem(str(int(i)+1))

                elif self.currentPage != self.pageNum:
                    self.currentPage = self.pageNum
                    page = self.currentPage
                    self.Page.addItem(str(page))

                self.comboxChange_()
                self.pageLast = len(self.imgList) % self.imgInPage

                time2 = time.time()
                print("time6-time5",time2-time1)

        except Exception as e:
            self.TextBrowser.append('Function:openIMG')
            self.TextBrowser.append(str(e))

    def ImgShowList(self,first,end):   #列表显示图像
        try:
            self.Piclist.clear()
            for i in self.imgList[first:end]:
                self.loadImages(i)
            # imgThread = threading.Thread(target=self.LoadImg_thread, args=(first,end))
            # imgThread.daemon = True
            # imgThread.start()
        except Exception as e:
            self.TextBrowser.append('Function:ImgShowList')
            self.TextBrowser.append(str(e))

    # def LoadImg_thread(self,first,end):
    #     for i in self.imgList[first:end]:
    #         self.loadImages(i)

    def FirstPage(self):  #首页
        try:
            if self.ButtonOpen == False:
                return
            if self.pageNum == 1:
                return
            self.Page.setCurrentIndex(0)
            self.ImgShowList(0, self.imgInPage)
        except Exception as e:
            self.TextBrowser.append('Function:FirstPage')
            self.TextBrowser.append(str(e))

    def LastPage(self):  #尾页
        try:
            if self.ButtonOpen == False:
                return
            if self.pageNum == 1:
                return
            self.Page.setCurrentIndex(self.pageNum-1)
            if self.pageLast == 0:
                self.pageLast = self.imgInPage
            self.ImgShowList(len(self.imgList)-self.pageLast, len(self.imgList))
        except Exception as e:
            self.TextBrowser.append('Function:LastPage')
            self.TextBrowser.append(str(e))

    def PrePage(self):   #前一页
        try:
            if self.ButtonOpen == False:
                return
            if self.pageNum == 1:
                return
            if self.Page.currentIndex() == 0:
                return
            self.Page.setCurrentIndex(self.Page.currentIndex() - 1)
            self.ImgShowList(self.Page.currentIndex()*self.imgInPage, self.Page.currentIndex()*self.imgInPage+self.imgInPage)

        except Exception as e:
            self.TextBrowser.append('Function:PrePage')
            self.TextBrowser.append(str(e))

    def NextPage(self):  #后一页
        try:
            if self.ButtonOpen == False:
                return
            if self.pageNum == 1:
                return
            if self.Page.currentIndex() == self.pageNum - 1:
                return
            if self.Page.currentIndex() == self.pageNum - 2:
                self.LastPage()
                return
            self.Page.setCurrentIndex(self.Page.currentIndex() + 1)
            self.ImgShowList(self.Page.currentIndex()*self.imgInPage, self.Page.currentIndex()*self.imgInPage+self.imgInPage)
        except Exception as e:
            self.TextBrowser.append('Function:NextPage')
            self.TextBrowser.append(str(e))

    def comboxChange(self):  #切换页数

        self.fanye.emit()

    def comboxChange_(self):
        try:
            if self.rundetect == True:
                if self.pageNum == 1:
                    if len(self.imgList) > self.imgInPage:
                        self.ImgShowList(0, self.imgInPage)
                    else:
                        self.ImgShowList(0, len(self.imgList))
                else:
                    self.ImgShowList((self.pageNum-1)  * self.imgInPage,
                                     (self.pageNum-1) * self.imgInPage + self.imgInPage)
                    self.Page.setCurrentIndex(self.pageNum-1)

            else:
                if self.Page.currentIndex() == 0:
                    if self.pageNum == 1:
                        self.ImgShowList(0, len(self.imgList))
                    else:
                        self.ImgShowList(0, self.imgInPage)

                else:
                    self.ImgShowList(self.Page.currentIndex() * self.imgInPage,
                                     self.Page.currentIndex() * self.imgInPage + self.imgInPage)
        except Exception as e:
            self.TextBrowser.append('Function:comboxChange')
            self.TextBrowser.append(str(e))

    def ClassChange(self):  #切换不同类别
        try:
            if self.ClassChange_ == 'detect':
                if self.ClassSelect.currentIndex() == 0:
                    self.openIMG(self.NGImgList+self.OKImgList,classchange=True)  # 显示图像
                if self.ClassSelect.currentIndex() == 1:
                    self.openIMG(self.NGImgList,classchange=True)  # 显示图像
                if self.ClassSelect.currentIndex() == 2:
                    self.openIMG(self.OKImgList,classchange=True)  # 显示图像
            if self.ClassChange_ == 'class':
                if self.ClassSelect.currentIndex() == 0:
                    list = []
                    for i in self.ClassPath:
                        list = list + scanAllImages(i)
                    self.openIMG(list)  # 显示图像

                else:
                    self.openIMG(scanAllImages(self.ClassPath[self.ClassSelect.currentIndex()-1])) # 显示图像

        except Exception as e:
            self.TextBrowser.append('Function:ClassChange')
            self.TextBrowser.append(str(e))

    def sacleImage(self, render):   ##加载大图
        try:
            self.img = QImage()
            self.currentImg = render.toolTip()
            self.currentImg = self.currentImg.replace('/','\\')
            self.ShowImg()
            self.graphicsView.setScene(self.graphicsView.scene)
            self.graphicsView.show()
        except Exception as e:
            self.TextBrowser.append('Function:sacleImage')
            self.TextBrowser.append(str(e))

    def NextImg(self):  #下翻一张
        try:
            index = self.imgList.index(self.currentImg)
            if index+1 == len(self.imgList):
                return
            if index == len(self.imgList):
                return
            self.currentImg = self.imgList[index+1]
            self.ShowImg()
        except Exception as e:
            self.TextBrowser.append('Function:NextImg')
            self.TextBrowser.append(str(e))

    def PreImg(self):  #上翻一张
        try:
            index = self.imgList.index(self.currentImg)
            if index == 0:
                return
            if index == len(self.imgList):
                return
            self.currentImg = self.imgList[index - 1]
            self.ShowImg()
        except Exception as e:
            self.TextBrowser.append('Function:PreImg')
            self.TextBrowser.append(str(e))

    def ShowImg(self):  #加载大图
        try:
            self.img.load(self.currentImg)
            if self.img.width() == None:
                return
            self.graphicsView.setWindowTitle(self.currentImg)
            self.graphicsView.setTransform(QTransform())

            rotation = get_rotation(self.currentImg)
            img = QPixmap().fromImage(self.img)
            img = img.transformed(QTransform().rotate(rotation))
            img = img.scaled(self.graphicsView.width(), self.graphicsView.height())

            self.graphicsView.scene.clear()
            self.graphicsView.scene.addPixmap(img)
        except Exception as e:
            self.TextBrowser.append('Function:ShowImg')
            self.TextBrowser.append(str(e))

    def loadImages(self,imgPath):  #显示图像
        try:
            rotation = get_rotation(imgPath)
            try:
                jpg = QPixmap(imgPath)
                pixmap = jpg.transformed(QTransform().rotate(rotation))
                icon = QIcon(pixmap)
            except:
                icon = QIcon(imgPath)
            iconName = os.path.basename(imgPath)
            a = QListWidgetItem(icon, str(iconName), self.Piclist)
            a.setToolTip(str(imgPath))
            self.Piclist.setViewMode(QListView.IconMode)
            self.Piclist.setMovement(QListView.Static)
            self.Piclist.setResizeMode(QListView.Adjust)
            self.Piclist.setSpacing(13)
            self.Piclist.setIconSize(QSize(230, 230))
            a.setSizeHint(QSize(250,272))

        except Exception as e:
            self.TextBrowser.append('Function:loadImages')
            self.TextBrowser.append(str(e))

def scanAllImages(folderPath):
    try:
        extensions = ['.%s' % fmt.data().decode("ascii").lower() for fmt in QImageReader.supportedImageFormats()]
        images = []
        for root, dirs, files in os.walk(folderPath):
            for file in files:
                if file.lower().endswith(tuple(extensions)):
                    relativePath = os.path.join(root, file)
                    path = str(os.path.abspath(relativePath))
                    images.append(path)
        images.sort(key=lambda x: x.lower())
        return images
    except Exception as e:
        pass

class ImageView(QGraphicsView):
    def __init__(self):
        super(ImageView, self).__init__()
        self.layout_()
        self.setDragMode(QGraphicsView.ScrollHandDrag)
        self.scene = QGraphicsScene()
        self.setScene(self.scene)

    def layout_(self):
        self.setGeometry(QRect(300, 30, 300, 50))
        self.setFixedSize(1200, 1000)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.buttonLeft = QPushButton('左')
        # self.buttonLeft.clicked.connect(self.PreImg)
        self.buttonLeft.setMaximumSize(30, 30)
        self.buttonRight = QPushButton('右')
        # buttonRight.clicked.connect(self.NextImg)
        self.buttonRight.setMaximumSize(30, 30)
        buttonLayout = QHBoxLayout()
        buttonLayout.addWidget(self.buttonLeft, Qt.AlignLeft)
        buttonLayout.addSpacing(5000)
        buttonLayout.addWidget(self.buttonRight, Qt.AlignRight)
        self.setLayout(buttonLayout)
        self.setObjectName("graphicsView")

    def wheelEvent(self, event):
        mods = event.modifiers()
        if Qt.ControlModifier == int(mods):
            self.scaleView(math.pow(2.0, event.angleDelta().y() / 240.0))

    def scaleView(self, scaleFactor):
        factor = self.transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width()

        if factor < 0.07 or factor > 100:
            return

        self.scale(scaleFactor, scaleFactor)

# if __name__ == '__main__':
#     app = QApplication(sys.argv)
#     w = TestWidget()
#     w.showMaximized()
#     w.show()
#     sys.exit(app.exec())
#








